home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
program
/
tdk_v120.zip
/
DOORKIT1.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-07-23
|
71KB
|
1,992 lines
{
▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀
▀▀ ▀▀ ▀▀ ▀▀ ▀▀
▀▀ ▀▀ ▀▀▀ ▀▀▀▀▀ The DoorKit!
▀▀ ▀▀ ▀▀ ▀▀ ▀▀
▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀
The BBS Door Development Kit By The People - For The People!
Feel free to modify or optimize this code at will. All I ask is that if
find a better way to do things (and you will), please send me a copy of
your modifications. Thanks in advance!....Larry L. Athey....
This is the primary DoorKit unit with all the critical SIO functions.
This unit also contains all of the main door variables and constants.}
{$A+,B-,D+,E+,F-,G-,I-,L+,N-,O-,P-,Q-,R-,S+,T-,V+,X+}
{$M 65520,0,655360}
UNIT DOORKIT1;
INTERFACE
USES _EXIT, CRT, DOS, ASYNC, FOSUNIT;
TYPE ControlFile = RECORD {Record of settings for each node}
Month : WORD; {The Month, Day, Year variables may be used at}
Day : WORD; {the programmers discretion. I use them in}
Year : WORD; {some doors to keep track of maintenance}
SFirst : STRING[20];{Sysop first name}
SLast : STRING[20];{Sysop last name}
SysSec : WORD; {Sysop security level on the BBS}
BBSname : STRING[40];{The name of the BBS}
SerialNumber : STRING[10];{Use this if you issue serial numbers}
HomePath : STRING[12];{BBS software home path, I use it for Shotgun}
UseFossil : BOOLEAN; {Use FOSSIL comm routines Yes/No}
PortSpeed : LONGINT; {Locked port speed (38000 max for FOSSIL)}
UseFIFOS : BOOLEAN; {Use FIFOs Yes/No}
WordSize : BYTE; {Data Bits (Normally set to 8)}
Parity : CHAR; {Parity O]dd E]ven N]one (Normally set to N)}
StopBits : BYTE; {Stop Bits (Normally set to 1)}
InBuffer : WORD; {Input buffer size (Default 512)}
OutBuffer : WORD; {Output buffer size (Default 1024)}
NSP : BOOLEAN; {Non-Standard port settings Yes/No}
Port : BYTE; {Comport number}
IRQ : BYTE; {Comport IRQ}
HexAddr : STRING[4]; {Comport Hex address}
END;
{NOTE: Not all settings in the control files are required. They are just
there in case you find a need for them. Adjust as needed....}
TYPE ColorScheme = RECORD {Record of system colors, expand this at will.}
Hfg, {Window header foreground}
Hbg, {Window header background}
Wbg, {Window background}
Sfg, {Window shadow foreground}
Sbg, {Window shadow background}
Wh, {Window highlight color}
Wl, {Window lowlight color}
Ffg, {Input field text foreground}
Fbg, {Input field text background}
Bfg, {Input field bracket foreground}
CPBfg, {CPrompt bracket foreground}
CPBbg, {CPrompt bracket background}
CPKfg, {CPrompt hotkey foreground}
CPKbg, {CPrompt hotkey background}
CPTfg, {CPrompt text foreground}
CPTbg, {CPrompt text background}
TxFG, {Text reader foreground}
TxBG : BYTE; {Text reader background}
END;
TYPE tScreen = ARRAY[0..24,0..159] OF BYTE;
tSystemEnv = (NoTasker,DDOS,DV,WIN,OS2,Network);
tWhichIO = (FossilIO,InternalIO);
{------------------------------------------------------------------------}
tDoor = RECORD {Record for the Door-System variables}
UserName : STRING[40];{User's real name}
Alias : STRING[40];{User's alias name}
PassWord : STRING[40];{User's password}
UserCity : STRING[40];{User's location}
Phone : STRING[15];{User's home/voice phone number}
WorkPhone : STRING[15];{User's work/data phone number}
BBSname : STRING[40];{The name of the BBS}
Access : WORD; {User's security level}
UserNumber : WORD; {User's record number}
Event : INTEGER; {Minutes until next event}
{------------------------------------------------------------------------}
Comport : BYTE; {Which Comport the program is using; 0=local}
BaudRate : LONGINT; {Baudrate for the comport}
WhichIO : tWhichIO; {Which IO routines to use (fossil or internal)}
IOinstalled : BOOLEAN; {comport IO routines installed?}
InBufSize : WORD; {Input buf size. (only for internal routines)}
OutBufSize : WORD; {Output buf size. (only for internal routines)}
IRQ : BYTE; {Which IRQ is being used}
WordSize : BYTE; {Wordsize (Data Bits) for comport}
Parity : CHAR; {Parity for comport; 'N'=none 'E'=even 'O'=odd}
StopBits : BYTE; {Stop Bits for comport}
Node : BYTE; {Which node the user is on}
{------------------------------------------------------------------------}
LocalInputON: BOOLEAN; {Enable/Disable local keyboard input}
UpdateLocal : BOOLEAN; {Writes to the local screen are allowed or not?}
{*} UpdateStatusBar: BOOLEAN;{Update status bar? (even if updatelocal=false)}
{*} UseVirtScr : BOOLEAN; {Use the virtual screen?}
StatusBarY : BYTE; {What line the status bar is displayed on}
LocalMaxY : BYTE; {# of lines (1-#) to update on local screen (usually 25)}
{------------------------------------------------------------------------}
SecondsLeft : LONGINT; {Seconds Left until user is booted back to BBS}
MinutesLeft : LONGINT; {Minutes Left until user is booted back to BBS}
{!} IdleCount : INTEGER; {How many seconds the user has been inactive}
UpdateSecs : BOOLEAN; {Update the user's remaining time?}
UpdateIdle : BOOLEAN; {Ckeck for user inactivity?}
{*} LocalKey : BOOLEAN; {Was the last key pressed local?}
OnLine : BOOLEAN; {Is user online/connected?}
{------------------------------------------------------------------------}
END;
{* Variables marked with an asterisk are "Read-Only" and should never be
modified or altered by your code. AGAIN! - DO NOT TAMPER WITH THESE!}
{! The IdleCount variable could cause you problems if you are writing any
kind of a door that forces the user to sit there without entering a key.
If any procedure or function in your program takes more than 300 seconds
to complete, you may want to add a hook in there to set this variable to
zero every once in a while. An example would be in an offline mail door,
every time the program packs one message add a DoorSys.IdleCount := 0;..}
CONST
VirtScr : ^tScreen = NIL; {Virtual Screen Record}
VirtX : INTEGER = 1; {Virtual X cursor position}
VirtY : INTEGER = 1; {Virtual Y cursor position}
WrapInput : BOOLEAN = FALSE;{Word wrap input fields Y/N?}
Local : BOOLEAN = TRUE; {Are we running in local mode?}
Tty = 0;
Ansi = 1;
Avatar = 2;
Rip = 3;
Max = 4;
Graphics : BYTE = Ansi; {Remote caller's graphics protocol}
UseDoorSys : BOOLEAN = TRUE; {Allow door to read DOOR.SYS?}
UseDorInfo : BOOLEAN = TRUE; {Allow door to read DORINFO#.DEF?}
_HangUp : BOOLEAN = FALSE;{Lower DTR before terminating?}
HideParams : BOOLEAN = FALSE;{Hide information when exiting door?}
UseTTY : BOOLEAN = FALSE;{Allow ASCII/TTY caller in the door?}
KillDrop : BOOLEAN = FALSE;{Delete drop file before terminating?}
Shotgun : BOOLEAN = FALSE;{Is this a Shotgun BBS system?}
IntConfig : BOOLEAN = FALSE;{Use internal configuration program?}
UseLocal : BOOLEAN = TRUE; {Allow local operation of the door?}
UseLog : BOOLEAN = FALSE;{Use activity logging?}
UseAd : BOOLEAN = TRUE; {Display program Ad upon startup?}
TYPE CursorMoveType = RECORD
Up : ARRAY[Tty..Avatar] OF STRING[3];
Down : ARRAY[Tty..Avatar] OF STRING[3];
Right : ARRAY[Tty..Avatar] OF STRING[3];
Left : ARRAY[Tty..Avatar] OF STRING[3];
Home : ARRAY[Tty..Avatar] OF STRING[3];
Endkey : ARRAY[Tty..Avatar] OF STRING[3];
Insert : ARRAY[Tty..Avatar] OF STRING[3];
Delete : ARRAY[Tty..Avatar] OF STRING[3];
END;
CONST
CursorMove : CursorMoveType = (Up : (#0+#72,#27'[A',#22+#3);
Down : (#0+#80,#27'[B',#22+#4);
Right : (#0+#77,#27'[C',#22+#6);
Left : (#0+#75,#27'[D',#22+#5);
Home : (#0+#71,#27'[H',#22+#0);
EndKey : (#0+#79,#27'[K',#22+#0);
Insert : (#0+#82,#22,#22);
Delete : (#0+#83,#127,#127));
VAR
CurTime : DATETIME; {The Current Time}
DropFilePath : STRING[80]; {Path to drop files}
Ctl : ControlFile;{Record for storing door setups per node}
CS : ColorScheme;{Record for storing various system colors}
DoorSys : tDoor; {Door-System variables}
StartTime : DATETIME; {When user entered door}
SystemEnv : tSystemEnv; {What OS is operating locally?}
BackSpaceChar : CHAR; {Character to use when the BS key is pressed}
LengthScr : BYTE; {Length of the remote caller's screen}
LogPath : STRING[80]; {Path to write activity log file}
LogFile : STRING[40]; {Activity log file name (Room for variables)}
UFirst : STRING[20]; {User's first name}
ULast : STRING[20]; {User's last name}
Insert1 : STRING[20];
Insert2 : STRING[20];
Insert3 : STRING[20];
Insert4 : STRING[20];
Insert5 : STRING[20]; {Various "Static" global system variables}
s_ReadKey : STRING[2]; {Local storage for sReadKey extended keys}
MaxID : STRING[4]; {For future development}
{─--[Headers]-──────────────────────────────────────────────────────────────}
PROCEDURE InitDoorKit;
{^ This procedure is like a "DO-ALL" procedure for starting up a door. This
eliminates the need for you to make a whole string of spaghetti at the
beginning of your program. Just set what ever variables you want that to
change from their default vaules (if needed) then call this procedure.}
PROCEDURE ReadCTL;
{^ This is used to read the settings for each node into the program and is
called automatically by InitDoorKit.}
PROCEDURE StartUpLog;
{^ This procedure is automatically called in the InitDoorKit procedure.
However, some people may choose to use node specific log files which
requires you to define your log file and path AFTER The DoorKit has
been initialized. You can then call this procedure AFTER The DoorKit
has been initialized and AFTER you have defined your LogFile/LogPath.}
PROCEDURE UpdateTime;
{^ If your door is busy (ie: Not at an sReadkey/sKeyPressed prompt) you will
want to occasionally call this procedure to be sure to update the user's
time. It would be best to call this procedure like every 5 or 10 seconds
so your program doesn't have to slow down for this procedure. Even if you
only call it every 10 seconds, 10 seconds will still be deducted from the
user's time. Be sure to see the variable DoorSys.IdleCount as well.}
FUNCTION InitComport : BOOLEAN;
{^ Initializes the comport for IO. This is normally the 2nd thing that is
called when your door starts (the 1st thing would either be reading a
DropFile, or INI file, or both). This must be called before any of the
other comport IO routines are called! (any procs. that use the modem).
No params are needed because all the values needed are taken from the
DoorSys record (Port,Baud,Parity), Set up all DoorSys variables first!
This isn't needed if you are using the InitDoorKit procedure.}
PROCEDURE DeInitComport;
{^ DeInitializes the comport. You can call this at the end of your door, but
you don't have to. It will be called automatically on its own at the end
of the program, its better if you don't call it. (see also: AddToExitChain)}
PROCEDURE ChangeIRQ(Comport,IRQ : BYTE);
{^ Assigns the IRQ for the comport. This is for comports that use nonstandard
IRQ only, if its a standard IRQ, then you don't need to call this. If this
ever needs to be called, it must be called before InitComport!
(This only works for the InternalIO!)}
PROCEDURE ChangeFIFO(Comport : BYTE; On : BOOLEAN);
{^ Lets you toggle the use of the receive FIFOs on the modem. By default the
FIFOs will NOT be used. That is to avoid the conficts with some modems
that have buggy FIFO's. Chances are that, this can be turned on without
any problems, most modems (if not all) these days have good FIFO buffers,
but some older or substandard ones might not.}
FUNCTION Carrier : BOOLEAN;
{^ Returns True if User is Connected, false if not. If DoorSys.Comport = 0
(local mode) then this will always return true.}
PROCEDURE Lower_DTR;
{^ Lowers the DTR (Drops Carrier) on the user.}
FUNCTION DataAvailable : BOOLEAN;
{^ Returns true if there is data available in the modem buffer.}
PROCEDURE TimeSlice;
{^ Gives up remaining CPU time to the rest of the OS. This procedure is set
up in the sReadkey function already, along with a few other procedures.
You can use it for your own needs as well.}
PROCEDURE BeginCritical;
{^ Begins a "Critical" block. After calling this under Multi-Tasking systems,
the majority of the CPU time will be given to your program, until you call
"EndCritical". This should be called right before sections of code that
need your program to be as smooth as possible. (If your not running under
a Multi-Tasking system, then this does nothing)}
PROCEDURE EndCritical;
{^ Ends a "Critical" block. This should be called after a call has been made
to "BeginCritical" and your critical section is done. (it does no harm if
BeginCritical was not called before this). Be sure to call this at some
point if you do call BeginCritical! Otherwise you'll probably slow down
the rest of the system until your door exits.}
PROCEDURE SendStr(S : STRING);
{^ This is used to send a string of data directly to the comport thus
bypassing any output to the local screen.}
PROCEDURE sCursorUp(N : BYTE);
PROCEDURE sCursorDown(N : BYTE);
PROCEDURE sCursorLeft(N : BYTE);
PROCEDURE sCursorRight(N : BYTE);
{^ Move the cursor n times in a any direction. If the cursor is already at
the maximum or minimum position in the direction its moving, it will not
move any further. This will only work if ANSI is enabled, otherwise any
calls to this procedure will be ignored.}
PROCEDURE sClrscr;
{^ Clears the screen with the current attribute.}
PROCEDURE sClrEol;
{^ Clears the current line starting from the current cursor position, to the
end of the line, w/o moving the cursor.....This happens on the remote and
local screen (according to UpdateLocal)....This will only work if ANSI is
enabled, otherwise any calls to this procedure will be ignored.}
PROCEDURE sGotoXY(X,Y : BYTE);
{^ Moves the cursor to the values in X,Y on the remote, and local screen
(according to UpdateLocal). The valid ranges are: X=1..80; Y=1..NumLines,
if either value is over the max range nothing will happen. This will only
work if ANSI is enabled.}
PROCEDURE FlushOutput;
{^ Flushes the output buffer. This procedure does not return until all the
output in the buffer has been sent to the remote.}
PROCEDURE PurgeOutPut;
{^ Purges all output in the Output buffer. Anything in the buffer is not
displayed (or sent to remote).}
PROCEDURE PurgeInput;
{^ Clears all input in the input buffer. Anything in the buffer will not be
read by the input routines.}
PROCEDURE sWriteC(C : CHAR);
PROCEDURE sWritelnC(C : CHAR); {append CRLF after the character}
{^ Writes a character to the comport, and the local screen (if UpdateLocal is
true).}
PROCEDURE sWriteN(N : LONGINT);
PROCEDURE sWritelnN(N : LONGINT); {append CRLF after the number}
{^ Writes any whole number to the comport, and the local screen (according to
UpdateLocal). You can use shortint,byte,integer,word & longints with this.
(You can also use: write(IO,'The Number is: ',mynumber)}
PROCEDURE sWrite(S : STRING);
PROCEDURE sWriteln(S : STRING); {append CRLF after the string}
{^ Writes a string to the comport, and the local screen (according to
UpdateLocal).}
FUNCTION sKeyPressed : BOOLEAN;
{^ Returns True if a local key has been pressed (if LocalInputON), or if a
key is waiting in the Input buffer (from remote).}
PROCEDURE sWaitInput(Ms : INTEGER);
{^ Waits for a keypress, or Ms milliseconds. Accurate to 10 milliseconds.}
FUNCTION sReadKey : CHAR;
{^ Reads either the first key in the INPUT buffer from the comport, or if a
local key was pressed. The scan code returned is just like TP's readkey.
(except Function keys (F1-F12, AltF1-AltF12))}
FUNCTION AnsiColor : STRING;
PROCEDURE SetFore(Fore : BYTE);
PROCEDURE SetBack(Back : BYTE);
PROCEDURE Set_Color(Fore,Back : BYTE);
{^ Sets the foreground and background colors to the values given. These
Procedures WILL actually send the ansi codes needed to change the color
to the remote screen, and change TextAttr locally. Repetetive color
changes of the same foreground and background are filtered from being
sent to the comport automatically (Makes for faster drawing).}
PROCEDURE ShowStatusBar;
{^ This redraws the Local Status Bar, but will not update the time variable
on the bar. This sets a window() so that the 25th line will not be
disturbed by the normal IO routines. If you want to write to the status
bar, then use the WriteStr() proc in the DOORIO unit. This will set
UpdateStatusBar := True.}
PROCEDURE HideStatusBar;
{^ This hides the Local Status Bar. This resets the window() so that the
25th line can be written to with the SIO routines. This will set
UpdateStatusBar := False.}
PROCEDURE Wait(Seconds : WORD);
{^ Wait a number of seconds. Seconds is not just an approximation like TP's
Delay procedure. This also does Time Slicing while waiting.}
FUNCTION InitVirtScr : BOOLEAN;
{^ Sets up the virtual screen to be used and sets the DoorSys variable for
it also. This virtual screen is maintained by all the output routines in
this library. When ever something is displayed to the player it is also
written to the virtual screen. When initializing the virtual screen,
After you call this function you should clear the screen (with a call to
sClrScr) to be sure that the screens get synchronized. This feature can
be useful for a couple of reasons: 1) This allows the user to "Refresh"
his/her screen anywhere in the door, if their screen gets garbled from
line noise or something. 2) If the door is running in Sysop Blockout Mode
(ie: nothing is being drawn to the local screen) and at some point the
door comes out of that mode, allowing the sysop to see what's going on
again...The door can update the local screen immediately. The only real
drawback to these routines is that they slow down the normal output
routines in this library, But it probably won't be noticable to anyone.}
PROCEDURE FreeVirtScr;
{^ Frees the Virtual Screen, and sets the DoorSys variable to reflect it.
After a call to this the Virtual Screen is not used, and will be a NIL
pointer if you try to access it. This is called automatically when the
program exits, so you don't have to call it.}
PROCEDURE DrawScr(Scr : POINTER; X1,Y1,X2,Y2 : BYTE);
{^ Refreshes the remote and local screens using the Virtual Screen. So that
must of been initialized first. Scr is a pointer to a buffer that holds
the screen. It must point to an array of tScreen, X1,Y1,X2,Y2 is the
rectangle to draw. The very last char in the bottom corner (80,25) will
NEVER be drawn. Otherwise the screen will scroll up.}
PROCEDURE AutoDetect;
{^ This proceudre is used to detect the remote graphics capabilities and
screen length. Note that the screen length may not be 100% accurate
due to the variations in terminal program design. This procedure also
detects the local operating system as well.}
PROCEDURE FakeVirus;
{^ Displays a bogus Telix file download screen that appears to transfer the
file VIRUS.COM to the user's C:\ directory and then drops carrier on them.
This is mainly for getting rid of problem users from the system. <G>}
PROCEDURE SplitUserName;
{^ In some cases you may need to change the DoorSys.UserName....After you do
that, you will need to refill the UFirst and ULast variables. That's what
this procedure does for you.}
PROCEDURE ReadDorInfo(DoorFn : PathStr; VAR DropInfo : tDoor);
{^ Reads a DORINFO#.DEF drop file into the DoorSys record.}
PROCEDURE ReadDoorSys(DoorFn : PathStr; VAR DropInfo : tDoor);
{^ Reads a DOOR.SYS drop file into the DoorSys record.}
PROCEDURE ShellToDos;
{^ *Just as it says, it shells the program to DOS.}
FUNCTION LocateFile(FName : STRING) : STRING;
{^ Locates a file in the DOS PATH and returns the full path & file name.}
PROCEDURE _Execute(FName,Params : STRING);
{^ *Runs an external executable/com with no screen save.}
PROCEDURE Execute(FName,Params : STRING);
{^ *Runs an exteral executable/com with text screen save.}
PROCEDURE RunBatFile(TheBat : STRING);
{^ *Runs a batch file with text screen save.}
{ *NOTE: When these processes run, only a 1.2K footprint of the program
is left in memory giving you the most RAM for child processes.}
IMPLEMENTATION
USES _SIO, EXEC, DOORKIT2;
CONST
F1 = #59; F2 = #60; F3 = #61; F4 = #62; F5 = #63;
F6 = #64; F7 = #65; F8 = #66; F9 = #67; F10 = #68;
AltF1 = #104; AltF2 = #105; AltF3 = #106; AltF4 = #107; AltF5 = #108;
AltF6 = #109; AltF7 = #110; AltF8 = #111; AltF9 = #112; AltF10 = #113;
{^ These are the constants for your sysop function keys. There is no
way for the remote to send these keys to your door.}
VAR
Buffer : ARRAY[1..4000] OF BYTE;
CurColor : BYTE;
ClockResult : LONGINT;
StopClock : LONGINT;
StartClock : LONGINT;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ClockOn;
VAR
S100 : WORD;
BEGIN
WITH CurTime DO BEGIN
GETTIME(Hour,Min,Sec,S100);
StartClock := (Hour * 3600) + (Min * 60) + Sec;
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ClockOff;
VAR
S100 : WORD;
BEGIN
WITH CurTime DO BEGIN
GETTIME(Hour,Min,Sec,S100);
StopClock := (Hour * 3600) + (Min * 60) + Sec;
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE UpdateTime;
BEGIN
ClockOff;
ClockResult := (StopClock - StartClock);
WITH DoorSys DO BEGIN
IF NOT Carrier THEN BEGIN
ErrLevel := 3;
HALT(ErrLevel);
END;
IF UpdateIdle THEN BEGIN
INC(IdleCount,ClockResult);
IF IdleCount = 300 THEN BEGIN {Halt for 5 minutes of user inactivity}
ErrLevel := 5;
HALT(ErrLevel);
END ELSE IF IdleCount = 60 THEN BEGIN {Wake-Up the caller after 60 secs}
IF NOT Local THEN SendStr(^G) ELSE WRITE(^G);
END;
END;
IF UpdateSecs THEN BEGIN
DEC(SecondsLeft,ClockResult);
IF SecondsLeft <= 0 THEN BEGIN
ErrLevel := 4;
HALT(ErrLevel);
END;
MinutesLeft := SecondsLeft DIV 60;
END;
END;
ClockOn;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION InitComport;
VAR
B : BOOLEAN;
BEGIN
InitComport := FALSE;
IF DoorSys.IOinstalled THEN EXIT;
DoorSys.IOinstalled := TRUE;
B := FALSE;
WITH DoorSys DO IF Comport > 0 THEN BEGIN
CASE WhichIO OF
InternalIO : BEGIN
B := OpenCom(Comport,InBufSize,OutBufSize);
IF B THEN ComParams(Comport,BaudRate,WordSize,Parity,StopBits)
END;
FossilIO : BEGIN
B := F_Init(Comport);
IF B THEN BEGIN
F_Parms(Comport,BaudRate,WordSize,Parity,StopBits);
F_Flow(Comport,TRUE);
END;
END;
END;
END ELSE B := TRUE;
IF NOT B THEN BEGIN
ErrLevel := 1;
ErrorLog('Cannot Initialize Comport!',ErrLevel,TRUE);
END;
DoorSys.IOinstalled := B;
IF (Not Carrier) THEN B := FALSE
ELSE BEGIN
PurgeOutput;
PurgeInput;
END;
InitComport := B;
DoorSys.Online := B;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE DeInitComport;
BEGIN
IF NOT DoorSys.IOinstalled THEN EXIT;
WITH DoorSys DO IF (Comport > 0) THEN
CASE WhichIO OF
InternalIO : BEGIN
SetRTSmode(Comport,FALSE,0,0);
SetCTSmode(Comport,FALSE);
CloseCom(Comport);
END;
FossilIO : F_Close(Comport);
END;
DoorSys.IOinstalled := FALSE;
DoorSys.Online := FALSE;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION Carrier;
BEGIN
IF DoorSys.Comport > 0 THEN BEGIN
CASE DoorSys.WhichIO OF
InternalIO : Carrier := DCDstat(DoorSys.Comport);
FossilIO : Carrier := F_CD(DoorSys.Comport);
END;
END ELSE BEGIN
Carrier := TRUE;
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ChangeIRQ;
BEGIN
C_PortInt[Comport] := IRQ;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ChangeFIFO;
BEGIN
C_FifoOK[Comport] := On;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION DataAvailable : BOOLEAN;
BEGIN
DataAvailable := False;
WITH DoorSys DO BEGIN
CASE WhichIO OF
InternalIO : DataAvailable := ComBufferLeft(Comport,'I') > 0;
FossilIO : DataAvailable := F_Avail(Comport);
END;
END;
END;
{ ────────────────────────────────────────────────────────────────────────── }
PROCEDURE Lower_DTR;
VAR
Regs : REGISTERS;
Loop : BYTE;
BEGIN
sWriteln(''); sWriteln('');
OutTxt(15,4,' CLICK! ');
IF Local THEN EXIT;
ErrLevel := 3;
Loop := 0;
REPEAT
INC(Loop);
Regs.DX := (DoorSys.ComPort - 1); {COM1=0, COM2=1, COM3=2, COM4=3}
Regs.AL := $00;
Regs.AH := $06;
INTR($14,Regs);
Wait(1);
SendStr('~~~+++~~~ATH0');
Wait(1);
UNTIL (NOT Carrier) OR (Loop = 5);
END;
{ ────────────────────────────────────────────────────────────────────────── }
PROCEDURE DetectOS; Assembler;
Asm
@CheckDV :
mov AX, $2B01
mov CX, $4445
mov DX, $5351
INT $21
cmp AL, $FF
je @CheckDoubleDOS
mov SystemEnv, DV
jmp @Done
@CheckDoubleDOS :
mov AX, $E400
INT $21
cmp AL, $00
je @CheckWindows
mov SystemEnv, DDOS
jmp @Done
@CheckWindows :
mov AX, $1600
INT $2F
cmp AL, $00
je @CheckOS2
cmp AL, $80
je @CheckOS2
mov SystemEnv, WIN
jmp @Done
@CheckOS2 :
mov AX, $3001
INT $21
cmp AL, $0A
je @InOS2
cmp AL, $14
jne @CheckNetwork
@InOS2 :
mov SystemEnv, OS2
jmp @Done
@CheckNetwork :
mov AX,$7A00
INT $2F
cmp AL,$FF
jne @NoTasker
mov SystemEnv, Network
jmp @Done
@NoTasker :
mov SystemEnv, NoTasker
@Done :
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE TimeSlice;
BEGIN
CASE SystemEnv OF
NoTasker : Asm INT $28 END;
DDOS : Asm mov ax,$EE01; INT $21 END;
DV : Asm mov ax,$1000; INT $15 END;
WIN,OS2 : Asm mov ax,$1680; INT $2F END;
Network : Asm mov bx,$000A; INT $7A END;
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE BeginCritical; Assembler;
Asm
cmp SystemEnv, DV
je @DVCrit
cmp SystemEnv, DDOS
je @DoubleDOSCrit
cmp SystemEnv, WIN
je @WinCrit
jmp @EndCrit
@DVCrit :
mov AX,$101B
INT $15
jmp @EndCrit
@DoubleDOSCrit :
mov AX,$EA00
INT $21
jmp @EndCrit
@WinCrit :
mov AX,$1681
INT $2F
jmp @EndCrit
@EndCrit :
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE EndCritical; Assembler;
Asm
cmp SystemEnv, DV
je @DVCrit
cmp SystemEnv, DDOS
je @DoubleDOSCrit
cmp SystemEnv, WIN
je @WinCrit
jmp @EndCrit
@DVCrit :
mov AX,$101C
INT $15
jmp @EndCrit
@DoubleDOSCrit :
mov AX,$EB00
INT $21
jmp @EndCrit
@WinCrit :
mov AX,$1682
INT $2F
jmp @EndCrit
@EndCrit :
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE SendStr(S : STRING);
BEGIN
IF Carrier THEN BEGIN
IF DoorSys.Comport > 0 THEN
CASE DoorSys.WhichIO OF
InternalIO : I_ComWrite(DoorSys.Comport,S);
FossilIO : F_Write(DoorSys.Comport,S);
END;
END ELSE BEGIN
DoorSys.Online := FALSE
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sCursorUp;
VAR
S : STRING[3];
BEGIN
WITH DoorSys DO IF (Graphics <> TTY) AND (VirtY > 1) THEN BEGIN
IF N > 1 THEN STR(N,S) ELSE S := '';
SendStr(#27'['+S+'A');
DEC(VirtY,N);
IF VirtY < 1 THEN VirtY := 1;
IF UpdateLocal THEN BEGIN
GOTOXY(VirtX,WhereY-N);
IF (VirtY <= DoorSys.LocalMaxY) THEN ShowCursor;
END;
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sCursorDown;
VAR
S : STRING[3];
BEGIN
WITH DoorSys DO IF (Graphics <> TTY) AND (VirtY < 25) THEN BEGIN
IF N > 1 THEN STR(N,S) ELSE S := '';
SendStr(#27'['+S+'B');
INC(VirtY,N);
IF VirtY > 25 THEN VirtY := 25;
IF UpdateLocal THEN BEGIN
GOTOXY(VirtX,WhereY+N);
IF (VirtY > DoorSys.LocalMaxY) THEN HideCursor;
END;
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sCursorRight;
VAR
S : STRING[3];
BEGIN
WITH DoorSys DO IF (Graphics <> TTY) AND (VirtX < 80) THEN BEGIN
IF N > 1 THEN STR(N,S) ELSE S := '';
SendStr(#27'['+S+'C');
INC(VirtX,N);
IF VirtX > 80 THEN VirtX := 80;
IF UpdateLocal THEN GOTOXY(VirtX,VirtY);
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sCursorLeft;
VAR
S : STRING[3];
I : BYTE;
BEGIN
WITH DoorSys DO IF (Graphics <> TTY) AND (VirtX > 1) THEN BEGIN
IF N > 80 THEN N := 80;
IF N > 1 THEN STR(N,S) ELSE S := '';
SendStr(#27'['+S+'D');
DEC(VirtX,N);
IF VirtX < 1 THEN VirtX := 1;
IF UpdateLocal THEN GOTOXY(VirtX,VirtY);
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sClrScr;
BEGIN
WITH DoorSys DO BEGIN
IF Graphics = TTY THEN SendStr(#12) ELSE SendStr(#27'[2J');
IF UpdateLocal THEN CLRSCR;
END;
VirtX := 1;
VirtY := 1;
IF DoorSys.UseVirtScr THEN FillWord(VirtScr^,SIZEOF(VirtScr^),TextAttr,' ');
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sClrEol;
BEGIN
WITH DoorSys DO IF Graphics <> TTY THEN BEGIN
SendStr(#27'[K');
IF UpdateLocal THEN CLREOL;
END;
IF DoorSys.UseVirtScr THEN FillWord(VirtScr^[VirtY-1,(VirtX-1)*2],(80-VirtX+1)*2,TextAttr,' ');
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sGotoXY;
BEGIN
WITH DoorSys DO IF Graphics <> TTY THEN BEGIN
SendStr(#27'['+IStr(Y,0)+';'+IStr(X,0)+'H');
IF UpdateLocal THEN BEGIN
GOTOXY(X,Y);
IF (Y > DoorSys.LocalMaxY) THEN HideCursor ELSE ShowCursor;
END;
END;
IF (X > 0) AND (X < 81) THEN VirtX := X;
IF (Y > 0) AND (Y < 26) THEN VirtY := Y;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION sKeyPressed;
VAR
B : BOOLEAN;
BEGIN
B := FALSE;
IF Carrier THEN BEGIN
IF DoorSys.Comport > 0 THEN
CASE DoorSys.WhichIO OF
InternalIO : B := ComBufferLeft(DoorSys.Comport,'I') > 0;
FossilIO : B := F_Avail(DoorSys.Comport);
END;
IF DoorSys.LocalInputON AND (NOT B) THEN B := KEYPRESSED;
END ELSE BEGIN
DoorSys.Online := FALSE;
END;
sKeyPressed := B;
IF NOT B THEN TimeSlice;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE FlushOutput;
BEGIN
IF (DoorSys.IOInstalled) AND (Carrier) THEN
CASE DoorSys.WhichIO OF
InternalIO : ComWaitForClear(DoorSys.Comport);
FossilIO : F_Flush(DoorSys.Comport);
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE PurgeOutput;
BEGIN
IF (DoorSys.IOInstalled) AND (DoorSys.Comport > 0) THEN
CASE DoorSys.WhichIO OF
InternalIO : ClearCom(DoorSys.Comport,'O');
FossilIO : F_Kill_Out(DoorSys.Comport);
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE PurgeInput;
BEGIN
IF (DoorSys.IOInstalled) AND (DoorSys.Comport > 0) THEN
CASE DoorSys.WhichIO OF
InternalIO : ClearCom(DoorSys.Comport,'I');
FossilIO : F_Kill_In(DoorSys.Comport);
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE DoVirt(C : CHAR; Yinc : BYTE); {Yinc should be ONLY 0 or 1!}
VAR
I : BYTE;
BEGIN
IF NOT (C IN [#07,#08,#10,#13]) THEN BEGIN
IF DoorSys.UseVirtScr THEN BEGIN
VirtScr^[VirtY-1,(VirtX-1)*2] := BYTE(C);
VirtScr^[VirtY-1,(VirtX-1)*2+1] := TextAttr;
END;
INC(VirtX);
END ELSE CASE C OF
{#07 : Cursor does not move.}
#08 : IF VirtX > 1 THEN DEC(VirtX);
#10 : INC(VirtY);
#13 : VirtX := 1;
END;
IF (VirtX > 80) OR (VirtY > 25) OR (Yinc > 0) THEN BEGIN
IF (VirtX > 80) THEN VirtX := 1;
IF VirtY < 25 THEN INC(VirtY) ELSE BEGIN
VirtY := 25;
IF DoorSys.UseVirtScr THEN BEGIN
MOVE(VirtScr^[1],VirtScr^[0],4000-160);
FillWord(VirtScr^[24],160,TextAttr,' ');
END;
END;
END;
IF (DoorSys.UpdateLocal) THEN IF (VirtY <= DoorSys.LocalMaxY) THEN ShowCursor ELSE HideCursor;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sWriteC;
BEGIN
IF Carrier THEN BEGIN
IF DoorSys.Comport > 0 THEN BEGIN
CASE DoorSys.WhichIO OF
InternalIO : ComWriteChW(DoorSys.Comport,C);
FossilIO : F_SendChar(DoorSys.Comport,C);
END;
END;
END ELSE DoorSys.Online := FALSE;
IF (DoorSys.UpdateLocal) THEN WRITE(C);
DoVirt(C,0);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sWritelnC;
BEGIN
IF Carrier THEN BEGIN
IF DoorSys.Comport > 0 THEN BEGIN
CASE DoorSys.WhichIO OF
InternalIO : I_ComWriteln(DoorSys.Comport,C);
FossilIO : F_Writeln(DoorSys.Comport,C);
END;
END;
END ELSE DoorSys.Online := FALSE;
IF (DoorSys.UpdateLocal) AND NOT ((VirtY >= DoorSys.LocalMaxY) AND (C = #10)) AND (VirtY = WhereY) THEN WRITELN(C);
DoVirt(C,1);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sWriteN;
VAR
I : INTEGER;
S : STRING[12];
BEGIN
STR(N,S);
FOR I := 1 TO LENGTH(S) DO sWriteC(S[I]);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sWritelnN;
VAR
I : INTEGER;
S : STRING[12];
BEGIN
STR(N,S);
FOR I := 1 TO LENGTH(S)-1 DO sWriteC(S[I]);
sWritelnC(S[I+1]);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sWrite;
VAR
I : INTEGER;
BEGIN
IF LENGTH(S) = 1 THEN sWriteC(S[1]) ELSE FOR I := 1 TO LENGTH(S) DO sWriteC(S[I]);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sWriteln;
VAR
I : INTEGER;
BEGIN
IF S = '' THEN BEGIN
WRITELN(SIO,'');
EXIT;
END;
IF LENGTH(S) = 1 THEN BEGIN
sWritelnC(S[1]);
EXIT;
END;
FOR I := 1 TO LENGTH(S)-1 DO sWriteC(S[I]);
WRITELN(SIO,S[I+1]);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE sWaitInput(Ms : INTEGER);
VAR
I : INTEGER;
BEGIN
I := Ms DIV 10;
WHILE NOT ((I = 0) OR sKeyPressed) DO BEGIN
DELAY(10);
DEC(I);
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE CheckFKeys(Ch : CHAR);
CONST
StatusType = 1 SHL 4 + 15;
Info = 1 SHL 4 + 11;
BEGIN
CASE Ch OF
F1 : WITH DoorSys DO IF UpdateStatusBar THEN BEGIN
UpdateStatusBar := FALSE;
DVWrite(1,StatusBarY,StatusType,' ');
DVWrite(2,StatusBarY,StatusType,'F1:'); DVWrite(5,StatusBarY,Info,'Toggle');
DVWrite(12,StatusBarY,StatusType,'F2:'); DVWrite(15,StatusBarY,Info,'Shell');
DVWrite(21,StatusBarY,StatusType,'F3:'); DVWrite(24,StatusBarY,Info,'Chat');
DVWrite(29,StatusBarY,StatusType,'F4:'); DVWrite(32,StatusBarY,Info,'FakeVirus');
DVWrite(42,StatusBarY,StatusType,'F5:'); DVWrite(45,StatusBarY,Info,'-5 Min');
DVWrite(52,StatusBarY,StatusType,'F6:'); DVWrite(55,StatusBarY,Info,'+5 Min');
DVWrite(62,StatusBarY,StatusType,'F9:'); DVWrite(65,StatusBarY,Info,'Eject');
DVWrite(71,StatusBarY,StatusType,'F10:'); DVWrite(75,StatusBarY,Info,'Drop');
DVWrite(61,24,8,'Free Memory: '+IntToStr(MEMAVAIL));
END ELSE BEGIN
UpdateStatusBar := TRUE;
ShowStatusBar;
DVWrite(61,24,8,'Free Memory: '+IntToStr(MEMAVAIL));
END;
F2 : ShellToDos;
F3 : ChatSelect;
F4 : FakeVirus;
F5 : WITH DoorSys DO BEGIN
DEC(SecondsLeft,5 * 60);
IF SecondsLeft < 0 THEN SecondsLeft := 1;
MinutesLeft := SecondsLeft DIV 60;
DVWrite(2,StatusBarY-1,11,'Minutes Left:');
DVWrite(16,StatusBarY-1,15,PadRight(IntToStr(MinutesLeft),' ',4));
END;
F6 : WITH DoorSys DO BEGIN
INC(SecondsLeft,5 * 60);
IF SecondsLeft > (24 * 60 * 60) THEN SecondsLeft := (24 * 60 * 60);
MinutesLeft := SecondsLeft DIV 60;
DVWrite(2,StatusBarY-1,11,'Minutes Left:');
DVWrite(16,StatusBarY-1,15,PadRight(IntToStr(MinutesLeft),' ',4));
END;
F7 : WITH DoorSys DO IF UpdateStatusBar THEN BEGIN
UpdateStatusBar := FALSE;
HideStatusBar;
END ELSE BEGIN
UpdateStatusBar := TRUE;
ShowStatusBar;
END;
F9 : HALT;
F10: BEGIN
IF NOT Local THEN _HangUp := TRUE;
HALT;
END;
END;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION sReadkey;
VAR
Ch : CHAR;
Found : BOOLEAN;
Cnt : BYTE;
LastCheck : BYTE;
S100 : WORD;
BEGIN
WITH CurTime DO GETTIME(Hour,Min,Sec,S100);
LastCheck := CurTime.Sec;
WITH DoorSys DO BEGIN
IdleCount := 0;
Cnt := 0;
Ch := #0;
Found := FALSE;
LocalKey := FALSE;
REPEAT
WITH CurTime DO GETTIME(Hour,Min,Sec,S100);
IF LastCheck <> CurTime.Sec THEN BEGIN
UpdateTime;
LastCheck := CurTime.Sec;
END;
IF (LocalInputON) AND (NOT Found) THEN BEGIN
IF KEYPRESSED THEN BEGIN
s_ReadKey := '';
Ch := READKEY;
s_ReadKey := s_ReadKey + Ch;
Found := (Ch <> #0);
IF Ch = #0 THEN BEGIN
Ch := READKEY;
s_ReadKey := s_ReadKey + Ch;
IF Ch IN [F1..F10,AltF1..AltF10] THEN CheckFKeys(Ch)
ELSE BEGIN
Ch := #0;
Found := TRUE;
LocalKey := TRUE;
END;
END ELSE LocalKey := TRUE;
END;
END;
IF (NOT Found) AND (Comport > 0) THEN BEGIN
CASE WhichIO OF
InternalIO : BEGIN
Found := ComBufferLeft(Comport,'I') > 0;
IF Found THEN Ch := ComReadCh(Comport);
LocalKey := NOT Found;
END;
FossilIO : BEGIN
Found := TRUE;
IF F_Avail(Comport) THEN Ch := F_ReadChar(Comport) ELSE Found := FALSE;
LocalKey := NOT Found;
END;
END;
END;
IF Cnt >= 100 THEN BEGIN
Cnt := 25;
TimeSlice;
END ELSE INC(Cnt);
UNTIL Found;
sReadKey := Ch;
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE SetFore;
BEGIN
Set_Color(Fore,TextAttr SHR 4);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE SetBack;
BEGIN
Set_Color(TextAttr MOD 16, Back);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE AddANSIcode(VAR St : STRING; StAdd : STRING);
BEGIN
IF St[LENGTH(St)] <> '[' THEN St := St + ';' + StAdd
ELSE St := St + StAdd;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION AnsiColor : STRING;
VAR
Temp : STRING;
CONST
AnsiColors : ARRAY[0..7] OF CHAR = '04261537';
BEGIN
Temp := '';
IF CurColor <> TextAttr THEN BEGIN
IF Graphics IN [Ansi,Rip] THEN BEGIN
Temp := #27'[';
IF TextAttr = LightGray THEN AddAnsiCode(Temp,'0') ELSE BEGIN
IF (TextAttr AND $8) <> (CurColor AND $8) THEN
IF (TextAttr AND $8 = $8) THEN AddAnsiCode(Temp,'1') ELSE BEGIN
CurColor := Lightgray;
Temp := #27'[0';
END;
IF (TextAttr AND $80) <> (CurColor AND $80) THEN
IF (TextAttr AND $80 = $80) THEN AddAnsiCode(temp,'5') ELSE BEGIN
CurColor := LightGray;
Temp := #27'[0';
IF (TextAttr AND $8 = $8) THEN AddAnsiCode(Temp,'1')
END;
IF (TextAttr AND $7) <> (CurColor AND $7) THEN
AddAnsiCode(Temp,'3' + AnsiColors[TextAttr AND $7]);
IF (TextAttr SHR $4) <> (CurColor SHR $4) THEN
AddAnsiCode(Temp,'4' + AnsiColors[(TextAttr SHR $4) AND $7]);
END;
Temp := Temp + 'm';
END ELSE IF Graphics = Avatar THEN BEGIN
Temp := #22#1 + CHAR(TextAttr AND $7F);
IF (TextAttr AND $80 = $80) THEN Temp := Temp + #22#2;
END;
END;
AnsiColor := Temp;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE Set_Color(Fore,Back : BYTE);
BEGIN
TextColor(Fore);
TextBackground(Back);
IF (NOT Local) AND (CurColor <> TextAttr) Then SendStr(AnsiColor);
CurColor := TextAttr;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ShowStatusBar;
CONST
StatusType = 1 SHL 4 + 15;
Info = 1 SHL 4 + 11;
SysopInfo = 1 SHL 4 + 14;
VAR
X,Y : BYTE;
BEGIN
DoorSys.UpdateStatusBar := TRUE;
DoorSys.LocalMaxY := DoorSys.StatusBarY-1;
X := VirtX;
Y := VirtY;
WINDOW(1,1,80,DoorSys.StatusBarY-1);
GOTOXY(X,Y);
IF (Y > DoorSys.LocalMaxY) THEN HideCursor;
WITH DoorSys DO BEGIN
DVWrite(1,StatusBarY,StatusType,' ');
DVWrite(2,StatusBarY,StatusType,'User:'); DVWrite(8,StatusBarY,Info,UserName);
DVWrite(28,StatusBarY,StatusType,'BPS:'); DVWrite(33,StatusBarY,Info,IntToStr(BaudRate));
DVWrite(39,StatusBarY,StatusType,'Node:'); DVWrite(45,StatusBarY,Info,IntToStr(Node));
DVWrite(49,StatusBarY,StatusType,'Sec:'); DVWrite(54,StatusBarY,Info,IntToStr(Access));
DVWrite(60,StatusBarY,StatusType,'Port:'); DVWrite(66,StatusBarY,Info,IntToStr(ComPort));
DVWrite(69,StatusBarY,SysopInfo,'(F1 : Help)');
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE HideStatusBar;
VAR
X,Y,A : BYTE;
BEGIN
DoorSys.UpdateStatusBar := FALSE;
DoorSys.LocalMaxY := DoorSys.StatusBarY;
X := VirtX;
Y := VirtY;
WINDOW(1,1,80,DoorSys.StatusBarY);
GOTOXY(1,DoorSys.StatusBarY);
A := TextAttr;
TextAttr := 7;
CLREOL;
TextAttr := A;
GOTOXY(X,Y);
ShowCursor;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE Wait;
VAR
U,Chs,Shs,CurSec,StartSec : WORD;
BEGIN
GETTIME(U,U,StartSec,Shs);
WHILE Seconds > 0 DO BEGIN
REPEAT
GETTIME(U,U,CurSec,Chs);
TimeSlice;
TimeSlice;
UNTIL (CurSec <> StartSec);
StartSec := CurSec;
DEC(Seconds);
END;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION InitVirtScr : BOOLEAN;
BEGIN
InitVirtScr := FALSE;
IF NOT DoorSys.UseVirtScr THEN BEGIN
IF (VirtScr = NIL) AND (MAXAVAIL > SIZEOF(VirtScr^)) THEN BEGIN
GETMEM(VirtScr,SIZEOF(VirtScr^));
FillWord(VirtScr^,SIZEOF(VirtScr^),7,' ');
VirtX := 1;
VirtY := 1;
DoorSys.UseVirtScr := TRUE;
END ELSE DoorSys.UseVirtScr := FALSE;
InitVirtScr := DoorSys.UseVirtScr;
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE FreeVirtScr;
BEGIN
IF VirtScr <> NIL THEN FREEMEM(VirtScr,SIZEOF(VirtScr^));
VirtScr := NIL;
DoorSys.UseVirtScr := FALSE;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE DrawScr(Scr : POINTER; X1,Y1,X2,Y2 : BYTE);
VAR
X,Y,VX,VY : BYTE;
BEGIN
VX := VirtX;
VY := VirtY;
IF scr = NIL THEN BEGIN
sClrScr;
END ELSE BEGIN
FOR Y := Y1-1 TO Y2-1 DO BEGIN
sGotoXY(X1,Y+1);
FOR X := X1-1 TO X2-1 DO IF (Y <> 25-1) OR (X <> 80-1) THEN BEGIN
TextAttr := tScreen(Scr^)[Y,(X*2)+1];
sWriteC(CHAR(tScreen(Scr^)[Y,(X*2)]));
END;
END;
sGotoXY(VX,VY);
END;
END;
{ ────────────────────────────────────────────────────────────────────────── }
PROCEDURE Autodetect;
VAR
RipG,
MaxG,
AnsiG,
AvatarG : BOOLEAN;
Loop : BYTE;
Ch : CHAR;
Temp : STRING;
Code : INTEGER;
BEGIN
RipG := FALSE;
MaxG := FALSE;
AvatarG := FALSE;
AnsiG := FALSE;
Graphics := Ansi;
MaxID := '';
{Detect RIP Graphics}
sClrScr;
OutTxt(5,0,'■ Detecting RIP Graphics.......');
Set_Color(0,0);
IF NOT Local THEN BEGIN
PurgeInput;
SendStr(AnsiColor+#27'[!');
Loop := 1;
REPEAT
DELAY(10);
INC(Loop);
UNTIL (Loop = 50) OR DataAvailable;
IF NOT Local THEN IF DataAvailable THEN RipG := TRUE;
END;
{Detect MAX Graphics}
IF RipG THEN BEGIN
sWriteln('');
OutTxt(5,0,'■ Detecting MAX Graphics.......');
Set_Color(0,0);
PurgeInput;
SendStr(#255'~'#255);
Loop := 1;
REPEAT
DELAY(10);
INC(Loop);
UNTIL (Loop = 150) OR DataAvailable;
IF DataAvailable THEN BEGIN
MaxG := TRUE;
RipG := FALSE;
WHILE DataAvailable DO BEGIN
Ch := sReadKey;
MaxID := MaxID + Ch;
END;
END;
END;
sWriteln('');
{Detect Ansi/Avatar Graphics}
OutTxt(5,0,'■ Detecting ANSI Graphics......');
Set_Color(0,0);
IF NOT Local THEN BEGIN
PurgeInput;
SendStr(AnsiColor+#22#8#2#70#27'[6n');
Loop := 1;
REPEAT
DELAY(10);
INC(loop);
UNTIL (Loop = 150) OR DataAvailable;
DELAY(50);
WHILE DataAvailable DO BEGIN
Ch := sReadKey;
IF Ch = '7' THEN AvatarG := TRUE;
IF Ch = '[' THEN AnsiG := TRUE;
END;
END;
sWriteln('');
IF RipG THEN Graphics := Rip ELSE
IF MaxG THEN Graphics := Max ELSE
IF AvatarG THEN Graphics := Avatar ELSE
IF AnsiG THEN Graphics := Ansi ELSE BEGIN
Graphics := Tty;
IF NOT Local THEN OutTxtL(4,0,'■ No Graphics Detected.........') ELSE Graphics := Ansi;
END;
IF (Graphics <> TTY) AND (Graphics <> MAX) THEN BEGIN
OutTxt(1,0,'■ Detecting Screen Length......');
Set_Color(0,0);
sCursorDown(25);
IF NOT Local THEN BEGIN
PurgeInput;
Temp := '';
SendStr(#27'[6n');
Loop := 1;
REPEAT
DELAY(10);
INC(loop);
UNTIL (Loop = 150) OR DataAvailable;
DELAY(50);
WHILE DataAvailable DO BEGIN
Ch := sReadKey;
Temp := Temp + Ch;
END;
VAL(COPY(Temp,3,POS(';',Temp)-3),LengthScr,Code);
IF Code <> 0 THEN LengthScr := 24;
END ELSE Lengthscr := HI(WindMax);
sGotoXY(1,4);
OutTxtL(1,0,'■ Screen Length Set To '+IntToStr(LengthScr)+' Rows.');
END;
IF Local THEN OutTxtL(9,0,'■ Local Mode Now Active........')
ELSE CASE Graphics OF
Rip : OutTxtL(9,0,'■ RIP Graphics Detected........');
Max : OutTxtL(9,0,'■ MAX Graphics Detected........');
Avatar : OutTxtL(9,0,'■ AVATAR Graphics Detected.....');
Ansi : OutTxtL(9,0,'■ ANSI Graphics Detected.......');
END;
Log('Screen Length Set To '+IntToStr(LengthScr)+' Rows');
sWriteln('');
Set_Color(11,0);
{Detect Local Operating System}
SystemEnv := NoTasker;
DetectOS;
CASE SystemEnv OF
NoTasker : sWriteln('■ No Multi-Tasker Detected.');
DDOS : sWriteln('■ Double-Dos Detected.');
DV : sWriteln('■ DesqView Detected.');
WIN : sWriteln('■ MS Windows Detected.');
OS2 : sWriteln('■ IBM OS/2 Detected.');
Network : sWriteln('■ Network Detected.');
END;
IF NOT Local THEN BEGIN
IF DoorSys.WhichIO = FossilIO THEN OutTxt(3,0,'■ Using Fossil Comm Routines.')
ELSE OutTxt(3,0,'■ Using Internal Comm Routines.');
END;
Wait(1);
TextAttr := 7;
END;
{ ────────────────────────────────────────────────────────────────────────── }
PROCEDURE ShutDownDoor; Far;
VAR
Loop : BYTE;
E,OsStr : STRING[40];
BEGIN
RipToText;
HideStatusBar;
NORMVIDEO;
FreeVirtScr;
TEXTBACKGROUND(0); CLRSCR;
IF KillDrop THEN BEGIN
FErase(DropFilePath+'DOOR.SYS');
FErase(DropFilePath+'DORINFO'+IntToStr(DoorSys.Node)+'.DEF');
END;
IF (Local) AND (ErrLevel = 3) THEN ErrLevel := 0;
CASE ErrLevel OF
0 : E := 'Normal Exit';
1 : E := 'Comm Port Error';
2 : E := 'Unable To Open Drop File';
3 : E := 'Carrier Lost';
4 : E := 'User Time Limit Expired';
5 : E := 'User Fell Asleep At The Keyboard';
6 : E := 'CRITICAL ERROR! - System File Missing';
END;
IF ErrLevel > 6 THEN E := 'SysOp Defined Exit';
IF (UseLog) And (LogFile <> '') THEN BEGIN
Log(E);
Log('Exiting At ErrorLevel '+IntToStr(ErrLevel));
Log('END');
END;
IF NOT HideParams THEN BEGIN
TEXTCOLOR(3);
DetectOS;
CASE SystemEnv OF
NoTasker : OsStr := 'DOS / No Multi-Tasker';
DDOS : OsStr := 'Double-Dos';
DV : OsStr := 'DesqView';
WIN : OsStr := 'MS Windows';
OS2 : OsStr := 'IBM OS/2';
Network : OsStr := 'Network';
END;
WRITELN;
WRITELN(' Program Name: ' + ProgramName);
WRITE(' Parameters Used: (');
FOR Loop := 1 TO PARAMCOUNT DO WRITE(AllCaps(PARAMSTR(Loop))+' ');
WRITELN(')');
WRITELN('Operating System: '+OsStr);
WRITELN(' Available Heap: '+IntToStr(MEMAVAIL));
WRITELN(' Error Level: '+IntToStr(ErrLevel));
WRITELN(' Exit Type: '+E);
TEXTCOLOR(7);
WRITELN; WRITELN;
IF ((NOT Carrier) AND (NOT Local)) OR (ErrLevel = 3) THEN HALT(3);
END;
IF (ErrLevel = 4) OR (ErrLevel = 5) OR (_HangUp) THEN Lower_DTR;
IF ((NOT Carrier) AND (NOT Local)) OR (ErrLevel = 3) THEN HALT(3);
FlushOutput;
DeInitComport;
Halt(ErrLevel);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE FakeVirus;
VAR
ProgCh : CHAR;
Col,
CPS,B,
Loop,L : WORD;
BEGIN
OutTxtXYL(11,5,15,1,'╒═╡ Zmodem Download ╞════════════════════════════════════╕');
OutTxtXYL(11,6,15,1,'│ │');
OutTxtXYL(11,7,15,1,'│ File name : │');
OutTxtXYL(11,8,15,1,'│ File path : │');
OutTxtXY(11,9,15,1,'│');OutTxt(14,1,' ──────────────────────────────────────────────────────');OutTxtL(15,1,' │');
OutTxtXY(11,10,15,1,'│');OutTxt(14,1,' Baud Rate : Approx CPS rate : ');OutTxtL(15,1,' │');
OutTxtXY(11,11,15,1,'│');OutTxt(14,1,' Transfer time : Bytes to send : ');OutTxtL(15,1,' │');
OutTxtXY(11,12,15,1,'│');OutTxt(14,1,' Time remaining : Bytes sent : ');OutTxtL(15,1,' │');
OutTxtXY(11,13,15,1,'│');OutTxt(14,1,' ──────────────────────────────────────────────────────');OutTxtL(15,1,' │');
OutTxtXYL(11,14,15,1,'│ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ Progress Ind. │');
OutTxtXY(11,15,15,1,'│');OutTxt(14,1,' ──────────────────────────────────────────────────────');OutTxtL(15,1,' │');
OutTxtXYL(11,16,15,1,'│ Last status/error : None │');
OutTxtXYL(11,17,15,1,'╘════════════════════════════════════════════════════════╛');
ProgCh := '█'; L := 0; B := 0; Col := 13;
IF Local THEN DoorSys.BaudRate := 14400;
CPS := DoorSys.BaudRate DIV 9;
OutTxtXY(30,10,14,1,IntToStr(DoorSys.BaudRate));
OutTxtXY(25,7,15,1,'VIRUS.COM');
OutTxtXY(25,8,15,1,'C:\');
OutTxtXY(30,11,14,1,'00:15');
OutTxtXY(30,12,14,1,'00:14');
OutTxtXY(58,10,14,1,IntToStr(CPS));
OutTxtXY(58,11,14,1,'4000');
FOR Loop := 1 TO 4000 DO BEGIN
INC(L); INC(B);
IF L = 100 THEN BEGIN
L := 0;
OutTxtXY(Col,14,15,1,ProgCh);
OutTxtXY(58,12,14,1,IntToStr(B));
DELAY(30);
INC(Col);
END;
END;
OutTxtXY(30,12,14,1,'00:00');
OutTxtXY(33,16,10,1,'Download Complete!');
AlertTones;
DELAY(2000);
Set_Color(7,0);
IF NOT Local THEN _HangUp := True;
HALT;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE SplitUserName;
VAR
Loop : BYTE;
FDone,
LDone : BOOLEAN;
BEGIN
UFirst := ''; ULast := ''; FDone := FALSE; LDone := TRUE;
FOR Loop := 1 TO LENGTH(DoorSys.UserName) DO BEGIN
IF DoorSys.UserName[Loop - 1] = ' ' THEN BEGIN
FDone := TRUE;
LDone := FALSE;
END;
IF (NOT FDone) AND (DoorSys.UserName[Loop] <> ' ') THEN UFirst := UFirst + DoorSys.UserName[Loop];
IF NOT LDone THEN ULast := ULast + DoorSys.UserName[Loop];
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ReadDorInfo(DoorFn : PathStr; VAR DropInfo : tDoor);
VAR
DoorDrop : Text;
Temp : STRING;
Code : INTEGER;
Temp2 : STRING;
Loop : BYTE;
BEGIN
IF (DoorFn <> '') THEN BEGIN
ASSIGN(DoorDrop,DoorFn);
RESET(DoorDrop);
END;
IF (IORESULT <> 0) OR (DoorFn = '') THEN BEGIN
TextAttr := 12;
WRITELN('Unable To Open '+DoorFn+'!');
ErrLevel := 2;
ErrorLog('Unable To Open '+DoorFn+'!',ErrLevel,TRUE);
END;
WITH DropInfo DO BEGIN
Node := BYTE(DoorFn[BYTE(DoorFn[0]) - LENGTH('.DEF')]) - 48;
READLN(DoorDrop,BBSname);
READLN(DoorDrop,Temp);
READLN(DoorDrop,Temp2);
READLN(DoorDrop,Temp);
VAL(COPY(Temp,4,255),Comport,Code);
Local := Comport = 0;
READLN(DoorDrop,Temp);
Loop := 1;
WHILE Temp[Loop] <> #32 DO INC(Loop);
Temp[0] := CHAR(loop - 1);
VAL(Temp,BaudRate,Code);
READLN(DoorDrop,Temp);
READLN(DoorDrop,Temp);
READLN(DoorDrop,Temp2);
IF Temp2 <> 'NLN' THEN UserName := Temp+' '+Temp2 ELSE UserName := Temp;
READLN(DoorDrop,UserCity);
READLN(DoorDrop,Graphics);
READLN(DoorDrop,Access);
READLN(DoorDrop,MinutesLeft);
SecondsLeft := MinutesLeft * LONGINT(60);
CLOSE(DoorDrop);
Phone := '123-456-7890';
WorkPhone := Phone;
Password := 'PASSWORD';
Alias := UserName;
END;
SplitUserName;
END;
{ ────────────────────────────────────────────────────────────────────────── }
PROCEDURE ReadDoorSys(DoorFn : PathStr; VAR DropInfo : tDoor);
VAR
DoorDrop : Text;
Temp : STRING;
Loop,Code : INTEGER;
BEGIN
IF (DoorFn <> '') THEN BEGIN
ASSIGN(DoorDrop,DoorFn);
RESET(DoorDrop);
END;
IF (IORESULT <> 0) OR (DoorFn = '') THEN BEGIN
TextAttr := 12;
WRITELN('Unable To Open '+DoorFn+'!');
ErrLevel := 2;
ErrorLog('Unable To Open '+DoorFn+'!',ErrLevel,TRUE);
END;
WITH DropInfo DO BEGIN
BBSname := 'The BBS';
READLN(DoorDrop,Temp);
VAL(COPY(Temp,4,LENGTH(Temp) - 4),Comport,Code);
Local := Comport = 0;
READLN(DoorDrop,Temp);
VAL(Temp,BaudRate,Loop);
READLN(DoorDrop,Temp);
READLN(DoorDrop,Node);
READLN(DoorDrop,Temp);
IF UPCASE(Temp[1]) <> 'N' THEN VAL(Temp,BaudRate,Loop);
FOR Loop := 1 TO 4 DO READLN(DoorDrop,Temp);
READLN(DoorDrop,UserName);
READLN(DoorDrop,UserCity);
READLN(DoorDrop,Phone);
READLN(DoorDrop,WorkPhone);
READLN(DoorDrop,Password);
READLN(DoorDrop,Access);
FOR Loop := 1 TO 3 DO READLN(DoorDrop,Temp);
READLN(DoorDrop,MinutesLeft);
SecondsLeft := Minutesleft * LONGINT(60);
Loop := 0;
CLOSE(DoorDrop);
RESET(DoorDrop);
WHILE NOT EOF(DoorDrop) DO BEGIN
INC(Loop);
READLN(DoorDrop,Temp);
IF Loop = 36 THEN Alias := Temp;
END;
IF Loop < 36 THEN Alias := UserName;
END;
CLOSE(DoorDrop);
SplitUserName;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE SaveScreen;
BEGIN
MOVE(Mem[$B800:0000],Buffer,4000);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE RestoreScreen;
BEGIN
MOVE(Buffer,Mem[$B800:0000],4000);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ShellToDos;
VAR
TheDir : STRING;
BEGIN
sWriteln(''); sWriteln('');
OutTxt(12,0,'The SysOp Has Shelled To DOS, Please Wait....');
GETDIR(0,TheDir);
CLRSCR;
PutEnv('PROMPT=Type: EXIT and press <ENTER> to return to '+ProgramName+'!$_$p$g');
Do_Exec(GetEnv('COMSPEC'),' /C ' + GetEnv('COMSPEC'),Use_All,$ffff,TRUE);
ShowStatusBar;
CHDIR(TheDir);
sClrScr;
OutTxtL(10,0,'The SysOp Has Returned From DOS....');
sWriteln('');
AnyKey;
END;
{───────────────────────────────────────────────────────────────────────────}
FUNCTION LocateFile(FName : STRING) : STRING;
VAR
F : STRING;
BEGIN
IF NOT FExist(FName) THEN BEGIN
F := FSearch(FName,GetEnv('PATH'));
LocateFile := FExpand(F);
EXIT;
END ELSE LocateFile := FName;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE _Execute(FName,Params : STRING);
VAR
TheDir : STRING;
BEGIN
FName := LocateFile(FName);
IF FName = '' THEN EXIT;
GETDIR(0,TheDir);
Do_Exec(FName,Params,Use_All,$ffff,TRUE);
CHDIR(TheDir);
DoorSys.IdleCount := 0;
UpdateTime;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE Execute(FName,Params : STRING);
VAR
TheDir : STRING;
BEGIN
FName := LocateFile(FName);
IF FName = '' THEN EXIT;
GETDIR(0,TheDir);
SaveScreen;
Do_Exec(FName,Params,Use_All,$ffff,TRUE);
RestoreScreen;
ShowStatusBar;
CHDIR(TheDir);
DoorSys.IdleCount := 0;
UpdateTime;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE RunBatFile(TheBat : STRING);
VAR
TheDir : STRING;
BEGIN
GETDIR(0,TheDir);
SaveScreen;
Do_Exec(GetEnv('COMSPEC'),' /C ' + TheBat,Use_All,$ffff,TRUE);
RestoreScreen;
ShowStatusBar;
CHDIR(TheDir);
DoorSys.IdleCount := 0;
UpdateTime;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE CommandLineHelp;
BEGIN
ShowProgramAd;
WRITELN;
TextAttr := 10;
WRITELN('Command Line Parameters');
LineBar(2,0,23);
TextAttr := 3;
IF UseDoorSys THEN WRITELN(PARAMSTR(0) + ' /D={Node Work Path}\DOOR.SYS');
IF UseDorInfo THEN WRITELN(PARAMSTR(0) + ' /R={Node Work Path}\DORINFO#.DEF');
WRITELN;
WRITELN('Add /N### To Force Node Number');
WRITELN('Add /S##### To Force Baud Rate');
WRITELN;
IF IntConfig THEN WRITELN('Use /CONFIG To Configure');
IF UseLocal THEN WRITELN('Use /L To Force Local Mode');
TextAttr := 7;
sGOTOXY(1,24);
AnyKey;
Halt(ErrLevel);
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE DoCommandLine;
VAR
ExtParams : BOOLEAN;
TempParam : STRING;
NewBaud : LONGINT;
NewNode,
Code : INTEGER;
Loop : BYTE;
BEGIN
NewNode := - 1;
NewBaud := 0;
Local := False;
IF PARAMCOUNT = 0 THEN CommandLineHelp;
FOR Loop := 1 TO PARAMCOUNT DO BEGIN
TempParam := AllCaps(PARAMSTR(Loop));
IF TempParam[1] = '/' THEN BEGIN
CASE TempParam[2] OF
'D' : BEGIN
ReadDoorSys(COPY(TempParam,4,255),DoorSys);
DropFilePath := GetFilePath(COPY(TempParam,4,255));
END;
'R' : BEGIN
ReadDorinfo(COPY(TempParam,4,255),DoorSys);
DropFilePath := GetFilePath(COPY(TempParam,4,255));
END;
'N' : BEGIN
VAL(COPY(TempParam,3,255),NewNode,Code);
IF Code <> 0 THEN BEGIN
WRITELN('Error In Forced Node Number: '+TempParam);
AlertTones;
ErrLevel := 1;
ErrorLog('Error In Forced Node Number: '+TempParam,ErrLevel,TRUE);
END;
END;
'S' : BEGIN
VAL(COPY(TempParam,3,255),NewBaud,Code);
IF Code <> 0 THEN BEGIN
WRITELN('Error In Forced Baud Rate: '+TempParam);
AlertTones;
ErrLevel := 1;
ErrorLog('Error In Forced Baud Rate: '+TempParam,ErrLevel,TRUE);
END;
END;
'L' : IF UseLocal Then Local := TRUE ELSE HALT;
'?' : CommandLineHelp;
'H' : CommandLineHelp;
'A',
'B',
'C',
'X',
'Y',
'Z' : ; {Scrap Parameters...No real reason for them to be here...}
ELSE BEGIN
CommandLineHelp;
END;
END;
END ELSE BEGIN
CommandLineHelp;
END;
END;
IF NewNode <> - 1 THEN DoorSys.Node := NewNode;
ReadCTL;
IF NewBaud <> 0 THEN DoorSys.BaudRate := NewBaud;
IF (NOT Local) AND (Ctl.NSP) AND (DoorSys.WhichIO = InternalIO) THEN BEGIN
C_PortAddr[Ctl.Port] := HexToInt(Ctl.HexAddr);
C_PortInt[Ctl.Port] := Ctl.IRQ;
DoorSys.Comport := Ctl.Port;
END;
IF NOT Local THEN InitComport;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE ReadCTL;
VAR
NodeStr : STRING[3];
CtlFile : File Of ControlFile;
BEGIN
STR(DoorSys.Node,NodeStr);
IF NOT FExist('NODE'+NodeStr+'.CTL') THEN BEGIN
sClrScr;
OutTxtL(15,4,'!!! FATAL ERROR !!!');
sWriteln('');
OutTxtL(12,0,'NODE'+NodeStr+'.CTL Not Found!');
sWriteln('');
OutTxtL(4,0,'Please Run The Configuration Program');
OutTxtL(4,0,'To Create A Control File For Node #'+NodeStr+'!');
AlertTones;
DELAY(2000);
ErrorLog('FATAL ERROR - NODE'+NodeStr+'.CTL NOT FOUND!',6,TRUE);
END;
ASSIGN(CtlFile,'NODE'+NodeStr+'.CTL');
RESET(CtlFile);
SEEK(CtlFile,0);
READ(CtlFile,Ctl);
CLOSE(CtlFile);
IF Ctl.HomePath = '\' THEN BEGIN
sClrScr;
OutTxtL(15,4,'!!! FATAL ERROR !!!');
sWriteln('');
OutTxtL(12,0,'No BBS Home Directory Defined In NODE'+NodeStr+'.CTL!');
sWriteln('');
OutTxtL(4,0,'Please Run The Configuration Program');
OutTxtL(4,0,'To Correct This Error...............');
AlertTones;
DELAY(2000);
ErrorLog('FATAL ERROR - No BBS Home Directory Defined In NODE'+NodeStr+'.CTL!',6,TRUE);
END;
IF POS('\SHOTGUN\',Ctl.HomePath) > 0 THEN Shotgun := TRUE;
WITH DoorSys DO IF NOT Local THEN BEGIN
IF Ctl.UseFossil THEN WhichIO := FossilIO ELSE WhichIO := InternalIO;
IF Ctl.UseFIFOS THEN ChangeFIFO(Ctl.Port,TRUE);
BaudRate := Ctl.PortSpeed;
WordSize := Ctl.WordSize;
Parity := Ctl.Parity;
StopBits := Ctl.StopBits;
InBufSize := Ctl.InBuffer;
OutBufSize := Ctl.OutBuffer;
END;
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE StartUpLog;
BEGIN
Log('BEGIN');
Log('Incoming Caller Connected At '+IntToStr(DoorSys.BaudRate)+' Baud');
Log('Free Memory: '+IntToStr(MEMAVAIL)+' Bytes');
CASE SystemEnv OF
NoTasker : Log('Running Under DOS / No Multi-Tasker');
DDOS : Log('Running Under Double-Dos');
DV : Log('Running Under DesqView');
WIN : Log('Running Under MS Windows');
OS2 : Log('Running Under IBM OS/2');
Network : Log('Running Under Network OS');
END;
IF DoorSys.WhichIO = FossilIO THEN Log('Using Fossil Comm Routines')
ELSE Log('Using Internal Comm Routines');
CASE Graphics OF
Rip : Log('RIP Graphics Detected');
Max : Log('MAX Graphics Detected');
Avatar : Log('AVATAR Graphics Detected');
Ansi : Log('ANSI Graphics Detected');
Tty : Log('No Graphics Detected');
END;
IF (Graphics <> TTY) AND (Graphics <> MAX) THEN Log('Screen Length Set To '+IntToStr(LengthScr)+' Rows');
END;
{───────────────────────────────────────────────────────────────────────────}
PROCEDURE InitDoorKit;
VAR
Ch : CHAR;
BEGIN
FileMode := 66;
ErrLevel := 0;
DoCommandLine;
IF DropFilePath = '' THEN DoorSys.Access := Ctl.SysSec;
IF Local THEN BEGIN
IF DoorSys.UserName = 'Joe User' THEN DoorSys.UserName := Ctl.SFirst+' '+Ctl.SLast;
IF DoorSys.Alias = 'Joe User' THEN DoorSys.Alias := DoorSys.UserName;
IF DoorSys.Access = 0 THEN DoorSys.Access := Ctl.SysSec;
DoorSys.BBSname := Ctl.BBSname;
UFirst := Ctl.SFirst;
ULast := Ctl.SLast;
END;
PurgeInput;
PurgeOutput;
AutoDetect;
StartUpLog;
IF Graphics = TTY THEN BEGIN
REPEAT;
sClrScr;
Set_Color(7,0);
sWriteln('');
sWriteln('ANSI Graphics Capabilities could not be detected in your terminal');
sWriteln('program. This program has features that use special cursor control');
sWriteln('routines that requires the user to have ANSI Graphics Capabilities.');
sWriteln('');
sWrite('Do you wish to attempt to force ANSI graphics on? [Y/N] ');
Ch := UPCASE(sReadKey);
sWriteln('');
UNTIL (Ch = 'Y') OR (Ch = 'N');
IF Ch = 'Y' THEN Graphics := ANSI;
IF NOT UseTTY THEN BEGIN
sWriteln('');
sWriteln(ProgramName+' Now Exiting!');
ErrLevel := 0;
HALT(ErrLevel);
END;
END;
DVWrite(61,24,8,'Free Memory: '+IntToStr(MEMAVAIL));
DELAY(500);
HideStatusBar;
ShowStatusBar;
TextAttr := 7;
sClrScr;
InitVirtScr;
PurgeInput;
PurgeOutput;
IF UseAd THEN ShowProgramAd;
END;
{───────────────────────────────────────────────────────────────────────────}
VAR
U : WORD;
BEGIN
GETTIME(StartTime.Hour,StartTime.Min,StartTime.Sec,U);
GETDATE(StartTime.Year,StartTime.Month,StartTime.Day,U);
AddtoExitChain(ShutDownDoor);
WITH CTL DO BEGIN
Month := StartTime.Month;
Day := StartTime.Day;
Year := StartTime.Year;
SFirst := 'The';
SLast := 'SysOp';
SysSec := 500;
BBSname := 'The BBS';
SerialNumber:= '';
HomePath := '';
UseFossil := TRUE;
PortSpeed := 38400;
UseFIFOS := TRUE;
WordSize := 8;
Parity := 'N';
StopBits := 1;
InBuffer := 512;
OutBuffer := 1024;
NSP := FALSE;
Port := 0;
IRQ := 4;
HexAddr := '03F8';
END;
WITH CS DO BEGIN
Hfg := 15;
Hbg := 3;
Wbg := 1;
Wh := 9;
Wl := 0;
Sfg := 8;
Sbg := 0;
Ffg := 15;
Fbg := 1;
Bfg := 14;
TxFG := 3;
TxBG := 0;
CPBfg := 9;
CPBbg := 0;
CPKfg := 14;
CPKbg := 0;
CPTfg := 13;
CPTbg := 0;
END;
WITH DoorSys DO BEGIN
UserName := 'Joe User';
Alias := UserName;
UserCity := 'AnyTown, AnyState';
PassWord := 'PASSWORD';
Phone := '123-456-7890';
WorkPhone := Phone;
BBSname := 'The BBS';
Access := 500;
UserNumber := 0;
Event := 1400;
ComPort := 0;
Baudrate := 0;
WhichIO := InternalIO;
IOinstalled := FALSE;
InBufSize := 512;
OutBufSize := 1024;
IRQ := 4;
WordSize := 8;
Parity := 'N';
StopBits := 1;
Node := 1;
LocalInputON:= TRUE;
UpdateLocal := TRUE;
UpdateStatusBar := TRUE;
UseVirtScr := FALSE;
StatusBarY := 25;
LocalMaxY := 25;
MinutesLeft := 1440;
SecondsLeft := MinutesLeft * LONGINT(60);
IdleCount := 0;
UpdateSecs := TRUE;
UpdateIdle := TRUE;
LocalKey := TRUE;
OnLine := TRUE;
END;
Local := FALSE;
CurColor := TextAttr;
BackSpaceChar := ' ';
ErrLevel := 0;
GetDir(0,LogPath);
LogPath := FixPath(LogPath);
LogFile := '';
DropFilePath := '';
ProgramName := 'No Program Name';
ProgramDesc := 'No Program Description';
ClockOn;
END.